-
Notifications
You must be signed in to change notification settings - Fork 94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix graphql node state and remove ghosts filters #4791
fix graphql node state and remove ghosts filters #4791
Conversation
How can we test that non-state updates get through though? (Damn, "through though" is indictment of the English language, innit). |
Opps, I meant graphql functional tests (and the entire CLI) all use the node filter I changed. |
012f667
to
42fb448
Compare
Yeah, but a UIS test maybe? |
Don't think we have and websockets tests for graphql subscriptions.. We just mock them all for queries.. Be easier once we can via the scheduler or command line via the hub. Something to look into for sure. |
42fb448
to
160d54c
Compare
Right issue? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that works 🎉
Integration test failures:
The last two are fixed by #4794 The first one is presumably genuine. |
772af16
to
f1fee39
Compare
Yeah, genuine.. I fixed the filter, we shouldn't really have any nodes (with state field) that have empty state, but possible if the node is added but not updated yet.. so handle this now. |
f1fee39
to
433b93f
Compare
I can't get this to hang locally though. |
433b93f
to
08dcb83
Compare
I put an error suppression around accessing the state from the data-store, I think it must be either the mock tests or the scenarios causing that point to fail (the store not to be available or something).. it was intermittent though.. |
It fixes an issue that make subscriptions appear not to work.. But probably not the same thing.. |
(Tests as working, but I'm slightly bamboozled by the logic above ... but maybe my brain is fried) |
GraphiQL still broken for me, could you explain what you mean by "appear not to work" to help me review. |
08dcb83
to
7fa56dd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @dwsutherland
Yours doesn't even get any data.. So I think it's a different issue, as this one you still got sent something but missed deltas. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I'm able to test this with GraphiQL broken for me (any ideas)? I'm also not sure I understand the problem this is fixing.
I've added a couple of questions in the review, would be really helpful to add a couple of code comments to clarify them.
or get_state_from_selectors(item) == state | ||
) | ||
) | ||
for item in uniq(items) | ||
) | ||
|
||
|
||
def node_filter(node, node_type, args): | ||
def node_filter(node, node_type, args, state): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not too clear on which bits belong to the node and which bits belong to the query?
Is the "state" the node state or the query state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
args
will have the query state to filter against
state
is the node state or data-store node state (if state isn't set in the delta, i.e. with outputs).
This ensures we always have a state to filter against (i.e. if we ever wanted to filter deltas by state, then deltas without a state field set can still be filtered by their data-store state)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cheers, so would this be correct?:
def node_filter(node, node_type, args, state):
"""Filter nodes based on attribute arguments
Args:
node: The node to filter (from the data or delta store).
node_type: The type of the node being filtered (or is it the type to filter by?)
args: The query arguments.
state: The state of the node that is being filtered.
Note: can be None for non-tasks e.g. task definitions where state filtering does not apply.
"""
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's right.
state is None | ||
or not args.get('states') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So if the node has no state (how does this happen?) then we include it in filter results irrespective of whether a query state was specified? Or am I misunderstanding?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So if the node has no state (how does this happen?)
It can happen if it's a task definition or something like that.
then we include it in filter results irrespective of whether a query state was specified?
Correct, as we use the same filter for nodes without states (task defs, family defs)
getattr(node, 'state', None) | ||
or self.data_store_mgr.data[ | ||
Tokens(node.id).workflow_id | ||
][node_type][node.id].state |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain what these two different methods mean?
- The first is getting the state from the node, the node as it exists in the data store?
- The second is getting the state from the data store directly. How does this differ from the node?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first is getting the state from the node, the node as it exists in the data store?
node
could be from a data-store or a delta-store.
The second is getting the state from the data store directly. How does this differ from the node?
Yes, if the first returns None
or empty string, fetch the state from the data-store...
If we want only deltas of specified state(s), then we need to filter out those deltas that don't contain state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that makes sense, is this right?:
return (
# try to retrieve the state from the node (could be a delta-store node)
getattr(node, 'state', None)
# fall back to the data store (because this could be a delta-store
# node which might not have the state field set)
or self.data_store_mgr.data[
Tokens(node.id).workflow_id
][node_type][node.id].state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct 👍
@@ -633,7 +632,6 @@ class Meta: | |||
lambda: TaskProxy, | |||
description="""Task cycle instances.""", | |||
args=PROXY_ARGS, | |||
ghosts=GHOSTS_DEFAULT, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really understand what "ghosts" were, why we had them or why we can dispense of them now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ghosts where part of a crude n-window (n=1) prototype... It has long been deprecated, and need to be removed..
It relates to this PR because it was in the part of the filter I had to change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so I can test this is still working correctly just be running the UI on a workflow and making sure the N=1 window shows as expected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Note the original motivation for this PR was cylc/cylc-uiserver#341 - i.e., custom task outputs not showing up at the UI in real time... which this PR definitely fixes.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so I can test this is still working correctly just be running the UI on a workflow and making sure the N=1 window shows as expected.
The current n-window implementation is orthogonal to that old prototype. These Ghosts literally weren't used anywhere, but the args were still in the API and in the node filtering.
But sure, test n=1
if you like :)
(will see if anyone else has working GraphiQL to review...) |
It fixes this issue: And the above gif in the comment; The fix is viewable in the UI tree view (don't need graphiql), see the above mentioned issue. |
Replicated cylc/cylc-uiserver#341, fixed the problem for me, 👍. |
(btw tested Tui too, all good) |
These changes partially address cylc/cylc-uiserver#341
Sibling PR cylc/cylc-ui#980
Delta's without a state field set will be filtered by state arguments... This is done by supplementing the node state using the data-store when not set..
Requirements check-list
CONTRIBUTING.md
and added my name as a Code Contributor.setup.cfg
andconda-environment.yml
.